package tools;

import java.util.Random;

import data.vectors.DoubleVector;
import data.vectors.DoubleVectorIterator;

public class MT {

	public static Random r;

	public static Double[] add(Double[] m1, Double[] m2) throws MatrixComputationException{
		if(m1.length != m2.length )
			throw new MatrixComputationException("size incompatibility");

		Double[] res =new Double[m1.length];
		for(int i=0; i<m1.length; i++)
			res[i] = m1[i] + m2[i];


		return res;
	}
	public static Double[] add(Double[] m1, Double m2) {

		Double[] res =new Double[m1.length];
		for(int i=0; i<m1.length; i++)
			res[i] = m1[i] + m2;


		return res;
	}

	public static Double scal(Double[] m1, Double[] m2) throws MatrixComputationException{
		if(m1.length != m2.length )
			throw new MatrixComputationException("size incompatibility");

		Double res = 0.;
		for(int i=0; i<m1.length; i++)
			res += m1[i] * m2[i];


		return res;
	}

	public static Double[] multp(Double[] m1, Double[] m2) throws MatrixComputationException{
		if(m1.length != m2.length )
			throw new MatrixComputationException("size incompatibility");

		Double res[] = zeros(m1.length);
		for(int i=0; i<m1.length; i++)
			res[i] = m1[i] * m2[i];


		return res;
	}

	public static Double[] multmat(Double[][] m, Double[] v) throws MatrixComputationException{
		if(v.length != m[0].length)
			throw new MatrixComputationException("size incompatibility");

		Double[] res =zeros(m.length);


		for(int i=0; i<m.length; i++)
			for(int j=0; j<m[0].length; j++){
				res[i] += m[i][j] * v[j];
			}

		return res;
	}

	public static Double[] multmat(Double[][] m, DoubleVector v) {

		Double[] res =zeros(m.length); // nlignes de m
		DoubleVectorIterator iter = v.getNonNullIterator();


		while(iter.hasNext()){
			iter.next();
			Double value = iter.getCurrentValue();
			int j = iter.getCurrentFeature();

			for(int i=0; i<m.length; i++)
				res[i] += m[i][j] * value;
		}

		return res;
	}




	public static Double[] zeros(int length) {
		Double[] res = new Double[length];
		for(int i=0; i<length; i++)
			res[i]=0.;

		return res;
	}

	public static Double[][] zeros(int x, int y) {
		Double[][] res = new Double[x][y];
		for(int i=0; i<x; i++)
			for(int j=0; j<y; j++)
				res[i][j]=0.;

		return res;
	}

	public static Double[] randn(int length) {
		Double[] res = new Double[length];
		for(int i=0; i<length; i++)
			res[i]=r.nextGaussian();

		return res;
	}

	public static Double[] rand(int length) {
		Double[] res = new Double[length];
		for(int i=0; i<length; i++)
			res[i]=r.nextDouble();

		return res;
	}

	public static Double[] tanh(Double[] v){
		Double[] res = new Double[v.length];
		for(int i=0; i<v.length; i++)
			res[i] = Math.tanh(v[i]);

		return res;
	}

	public static Double[] dtanh(Double[] v){
		Double[] res = new Double[v.length];
		for(int i=0; i<v.length; i++)
			res[i] = 1+Math.tanh(v[i])*Math.tanh(v[i]);

		return res;
	}
	public static Double[][] multTable(Double[] v1, Double[] v2) {


		Double[][] res = new Double[v1.length][v2.length];


		for(int i=0; i<v1.length; i++)
			for(int j=0; j<v2.length; j++){
				res[i][j] = v1[i] * v2[j];
			}

		return res;
	}
	public static Double[] factor(double d, Double[] v) {
		Double[] res = new Double[v.length];
		for(int i=0; i<v.length; i++)
			res[i] = d*v[i];

		return res;
	}
	public static Double[][] multTable(Double[] v, DoubleVector x, int sX) {
		Double[][] res = zeros(v.length,sX);

		DoubleVectorIterator iter = x.getNonNullIterator();


		while(iter.hasNext()){
			iter.next();
			Double value = iter.getCurrentValue();
			int j = iter.getCurrentFeature();

			for(int i=0; i<v.length; i++)
				res[i][j] = v[i] * value;
		}

		return res;
	}
	public static void maj(Double[][] phi1, Double[][] dPhi1, double epsilon) throws MatrixComputationException {
		
		if(phi1[0].length != dPhi1[0].length || phi1.length != dPhi1.length)
			throw new MatrixComputationException("size incompatibility");
		
		for(int i=0; i<phi1.length; i++)
			for(int j=0; j<phi1[0].length; j++){
				phi1[i][j] = phi1[i][j] - epsilon * dPhi1[i][j];
			}
	}
	public static void maj(Double[] w, Double[] dW, double epsilon) throws MatrixComputationException {
		if( w.length != dW.length)
			throw new MatrixComputationException("size incompatibility");
		
		for(int i=0; i<w.length; i++)
				w[i] = w[i] - epsilon * dW[i];
			
		
	}
}
